{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'''\n",
    "流程：1.准备样本 2.训练 3.预测\n",
    "正样本（820个）：pos包含所要检测的目标对象 负样本（1931个）：neg不包含所要检测的目标对象\n",
    "正负样本比例：1:2 ~ 1:3之间\n",
    "正样本应该尽可能的多样：环境多样 干扰多样\n",
    "一个好的样本远胜于复杂的神经网络，机器学习需要的样本比深度学习少\n",
    "收集样本：1.向相关公司购买 2.网络爬取数据 3.公司内部多年积累的数据\n",
    "'''\n",
    "import cv2\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 1.参数设置\n",
    "# 正负样本个数\n",
    "PosNum = 820\n",
    "NegNum = 1931\n",
    "# 窗体大小\n",
    "winSize = (64,128)\n",
    "# block大小以及步长\n",
    "blockSize = (16,16)\n",
    "blockStride = (8,8)\n",
    "# cell范围\n",
    "cellSize = (8,8)\n",
    "# bin数量\n",
    "nBin = 9\n",
    "# 2.HOG创建\n",
    "hog = cv2.HOGDescriptor(winSize,blockSize, blockStride,cellSize,nBin)\n",
    "# 3.SVM的创建\n",
    "svm = cv2.ml.SVM_create()\n",
    "# 4.计算hog(3780)并标注标签\n",
    "featureNum = int(((128-16)/8+1)*((64-16)/8+1)*4*9) \n",
    "featureArray = np.zeros(((PosNum+NegNum),featureNum),np.float32)\n",
    "labelArray = np.zeros(((PosNum+NegNum),1),np.int32)\n",
    "# 计算正样本hog特征\n",
    "for i in range(0,PosNum):\n",
    "    fileName = 'pos\\\\'+str(i+1)+'.jpg'\n",
    "    img = cv2.imread(fileName,1)\n",
    "    hist = hog.compute(img,(8,8))\n",
    "    # hog特征装载\n",
    "    for j in range(0,featureNum):\n",
    "        featureArray[i,j] = hist[j] \n",
    "    # 正样本label为1\n",
    "    labelArray[i,0] = 1\n",
    "# 计算负样本hog特征\n",
    "for i in range(0,NegNum):\n",
    "    fileName = 'neg\\\\'+str(i+1)+'.jpg'\n",
    "    img = cv2.imread(fileName,1)\n",
    "    hist = hog.compute(img,(8,8))\n",
    "    # hog特征装载\n",
    "    for j in range(0,featureNum):\n",
    "        featureArray[i+PosNum,j] = hist[j] \n",
    "    # 负样本label为-1\n",
    "    labelArray[i+PosNum,0] = -1\n",
    "# SVM属性设置\n",
    "svm.setType(cv2.ml.SVM_C_SVC)\n",
    "# 设置内核为线性分类器\n",
    "svm.setKernel(cv2.ml.SVM_LINEAR)\n",
    "svm.setC(0.01)\n",
    "# 5.训练\n",
    "result = svm.train(featureArray,cv2.ml.ROW_SAMPLE,labelArray)\n",
    "# 6.检测（创建myHog进行检测）\n",
    "alpha = np.zeros((1),np.float32)\n",
    "# 得到hog描述信息用于判决\n",
    "rho = svm.getDecisionFunction(0,alpha)\n",
    "alphaArray = np.zeros((1,1),np.float32)\n",
    "svmArray = np.zeros((1,featureNum),np.float32)\n",
    "# 3780维\n",
    "resultArray = np.zeros((1,featureNum),np.float32)\n",
    "alphaArray[0,0] = alpha\n",
    "# 支持向量的个数\n",
    "resultArray = -1*alphaArray*svmArray\n",
    "# 3780 + 1 = 3781维 3780来自resultArray 1来自rho\n",
    "detect = np.zeros((3781),np.float32)\n",
    "for i in range(0,3780):\n",
    "    detect[i] = resultArray[0,i]\n",
    "detect[3780] = rho[0]\n",
    "myHog = cv2.HOGDescriptor()\n",
    "myHog.setSVMDetector(detect)\n",
    "# 加载待检测图片\n",
    "imgSrc = cv2.imread('Test2.jpg',1)\n",
    "# 检测出目标的信息 \n",
    "# 参数1：图片 参数2: 灰度图像 参数3：winStride 参数4：窗体大小 参数5：缩放系数 参数6：目标大小单位为像素\n",
    "objects = myHog.detectMultiScale(imgSrc,0,(8,8),(32,32),1.05,2)\n",
    "# 起始位置以及宽高x,y,w,h存放在最后一维\n",
    "x = int(objects[0][0][0])\n",
    "y = int(objects[0][0][1])\n",
    "w = int(objects[0][0][2])\n",
    "h = int(objects[0][0][3])\n",
    "# 绘制并展示\n",
    "cv2.rectangle(imgSrc,(x,y),(x+w,y+h),(255,0,0),2)\n",
    "cv2.imshow('dst',imgSrc)\n",
    "cv2.waitKey(0)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
